#include "msp430g2553.h"
#include <stdio.h>

// Hardware-related definitions
#define UART_TXD   0x02                     // TXD on P1.1 (Timer0_A.OUT0)
#define UART_RXD   0x04                     // RXD on P1.2 (Timer0_A.CCI1A)

// Conditions for 9600 Baud SW UART, SMCLK = 1MHz
#define UART_TBIT_DIV_2     (1000000 / (9600 * 2))
#define UART_TBIT           (1000000 / 9600)

// Global variables used for serial Comm
unsigned int txData;                        // UART internal variable for TX
unsigned char rxBuffer;                     // Received UART character

//------------------------------------------------------------------------------
// Function prototypes
//------------------------------------------------------------------------------
void TimerA_UART_init(void);
void TimerA_UART_tx(unsigned char byte);
void TimerA_UART_print(char *string);
void init(void);
void xBeeTx(char *data, short size);
//------------------------------------------------------------------------------
// main()
//------------------------------------------------------------------------------
void main(void)
{
	init();
    __enable_interrupt();

    TimerA_UART_init();                     // Start Timer_A UART
    TimerA_UART_print("OMG UART WORKS!!!\r\n");
	char test [] = {0xFF, 0xFF, 0xFF};
    while(1)
    {
    	short length = sizeof(test)*sizeof(char);
        // Wait for incoming character
        __bis_SR_register(LPM0_bits);
		if(rxBuffer == 'T')
			xBeeTx(test, length);

        // Echo received character
       // TimerA_UART_tx(rxBuffer);
    }
}

void init(void)
{
    WDTCTL = WDTPW + WDTHOLD;               // Stop watchdog timer

    DCOCTL = 0x00;                          // Set DCOCLK to 1MHz
    BCSCTL1 = CALBC1_1MHZ;
    DCOCTL = CALDCO_1MHZ;

    P1OUT = 0x00;                           // Initialize all GPIO
    P1SEL = UART_TXD + UART_RXD;            // Timer function for TXD/RXD pins
    P1DIR = 0xFF & ~UART_RXD;               // Set all pins but RXD to output
    P2OUT = 0x00;
    P2SEL = 0x00;
    P2DIR = 0xFF;
}

// Function configures Timer_A for full-duplex UART operation
void TimerA_UART_init(void)
{
    TACCTL0 = OUT;                          // Set TXD Idle as Mark = '1'
    TACCTL1 = SCS + CM1 + CAP + CCIE;       // Sync, Neg Edge, Capture, Int
    TACTL = TASSEL_2 + MC_2;                // SMCLK, start in continuous mode
}

// Outputs one byte using the Timer_A UART
void TimerA_UART_tx(unsigned char byte)
{
    while (TACCTL0 & CCIE);                 // Ensure last char got TX'd
    TACCR0 = TAR;                           // Current state of TA counter
    TACCR0 += UART_TBIT;                    // One bit time till first bit
    TACCTL0 = OUTMOD0 + CCIE;               // Set TXD on EQU0, Int
    txData = byte;                          // Load global variable
    txData |= 0x100;                        // Add mark stop bit to TXData
    txData <<= 1;                           // Add space start bit
}


// Prints a string over using the Timer_A UART
void TimerA_UART_print(char *string)
{
    while (*string)
    {
        TimerA_UART_tx(*string++);
    }
}

// Timer_A UART - Transmit Interrupt Handler
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A0_ISR(void)
{
    static unsigned char txBitCnt = 10;

    TACCR0 += UART_TBIT;                    // Add Offset to CCRx
    if (txBitCnt == 0)
    {					                    // All bits TXed?
        TACCTL0 &= ~CCIE;                   // All bits TXed, disable interrupt
        txBitCnt = 10;                      // Re-load bit counter
    }
    else
    {
        if (txData & 0x01)
        {
          TACCTL0 &= ~OUTMOD2;              // TX Mark '1'
        }
        else {
          TACCTL0 |= OUTMOD2;               // TX Space '0'
        }
        txData >>= 1;
        txBitCnt--;
    }
}

// Timer_A UART - Receive Interrupt Handler
#pragma vector = TIMER0_A1_VECTOR
__interrupt void Timer_A1_ISR(void)
{
    static unsigned char rxBitCnt = 8;
    static unsigned char rxData = 0;

    switch (__even_in_range(TA0IV, TA0IV_TAIFG))
    {
        case TA0IV_TACCR1:                        // TACCR1 CCIFG - UART RX
            TACCR1 += UART_TBIT;                 // Add Offset to CCRx
            if (TACCTL1 & CAP)
            {					                 // Capture mode = start bit edge
                TACCTL1 &= ~CAP;                 // Switch capture to compare mode
                TACCR1 += UART_TBIT_DIV_2;       // Point CCRx to middle of D0
            }
            else
            {
                rxData >>= 1;
                if (TACCTL1 & SCCI)
                {            // Get bit waiting in receive latch
                    rxData |= 0x80;
                }
                rxBitCnt--;
                if (rxBitCnt == 0)
                {             // All bits RXed?
                    rxBuffer = rxData;           // Store in global variable
                    rxBitCnt = 8;                // Re-load bit counter
                    TACCTL1 |= CAP;              // Switch compare to capture mode
                    __bic_SR_register_on_exit(LPM0_bits);  // Clear LPM0 bits from 0(SR)
                }
            }
            break;
    }
}
// UART to comply with MAGE Server integration
void xBeeTx(char *data, short length)
{
	short i;
	TimerA_UART_tx(0x7E);	//start delimiter
	TimerA_UART_tx(0x00);
	TimerA_UART_tx(0x0B);	// data length
	TimerA_UART_tx(0x01);
	TimerA_UART_tx(0x01);
	//for(i = 0; i < 8; i++)
	//	TimerA_UART_tx(0x00);	// 64 bits of 0 for Dest Add.
	TimerA_UART_tx(0xFF);		// 16 bit destination
	TimerA_UART_tx(0xFF);
	TimerA_UART_tx(0x01);		// range max
	TimerA_UART_tx(0xFF);		// options

	// Destination
	TimerA_UART_tx(0xFF);
	TimerA_UART_tx(0x10);
	//Source
	TimerA_UART_tx(0x0F);
	TimerA_UART_tx(0x00);
	TimerA_UART_tx(0x00);
	// all this for just a small bit of data...
    //for(i = 0; i < length; i ++)
    //{
    //    TimerA_UART_tx(*data++);
    //}
	TimerA_UART_tx(0xE1);
}
